﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace InDepth2Demo.Chapter9
{
    /// <summary>
    /// 9.2 使用 List<T>和事件的简单例子
    /// </summary>
    public class LambdaDemo
    {
        //为了使代码尽可能简洁，我们将使用自动实现的属性、隐式类型的局部变量以及集合初始化列表。然后，我们将调用要求获取委托参数的方法——当然，是用Lambda表达式来创建委托。

        // 需求：程序先打印原始列表，然后创建并打印只包含老电影的一个已筛选列表。最后，我们按电影名称排序并打印原始列表。（思考假如换用C# 1来做同样的事情）

        public static void Call()
        {
            var films = new List<Film>
            {
                new Film { Name = "Jaws",Year = 1975 },
                new Film { Name = "Singing in the Rain",Year = 1952 },
                new Film { Name = "Some Like it Hot",Year = 1959 },
                new Film { Name ="The wizard of0z",Year =1939 },
                new Film { Name="It's a Wonderful Life", Year = 1946 },
                new Film { Name="American Beauty",Year = 1999},
                new Film { Name = "High Fidelity",Year = 2000},
                new Film { Name = "The Usual Suspects", Year = 1995 },

            };
            Action<Film> print = film => Console.WriteLine($"Name={film.Name},Year={film.Year}");   //创建可重用的列表打印委托
            films.ForEach(print);                   //打印原始列表

            films.FindAll(film => film.Year < 1960)         // 创建筛选过的队列     // 源代码将Lambda表达式作为一个方法实参来使用
                .ForEach(print);

            films.Sort((f1, f2) => f1.Name.CompareTo(f2.Name));      // 排序原始列表
            films.ForEach(print);


            // 所以调用 FindAll 的方法实际会变成：
            films.FindAll(new Predicate<Film>(SomeAutoGeneratedName));
        }

        // (film => film.Year < 1960)       // 源代码将Lambda表达式作为一个方法实参来使用，但实际编译器会创建下面这样的一个方法：
        private static bool SomeAutoGeneratedName(Film film)
        {
            return film.Year < 1960;
        }

        // 所以调用 FindAll 的方法实际会变成：
        // films.FindAll(new Predicate<Film>(SomeAutoGeneratedName));

        class Film
        {
            public string Name { get; set; }
            public int Year { get; set; }
        }
    }

    public class CSharp1Code
    {
        public static void Call()
        {
            //List<Film> films = new List<Film>();    // 这似乎是 C#2 的强类型集合
            //films.Add(new Film("Jaws", 1975));
            //films.Add(new Film("Singing in the Rain", 1952));

            ArrayList films = new ArrayList();  //要装箱和拆箱
            films.Add(new Film("Jaws", 1975));
            films.Add(new Film("Singing in the Rain", 1952));
            films.Add(new Film("American Beauty", 1999));

            foreach (Film film in films)            // 打印原始集合
            {
                Console.WriteLine($"Name={film.Name},Year={film.Year}");
            }

            ArrayList filterFilms = new ArrayList();       // 创建筛选过的队列
            foreach (object item in films)
            {
                Film film = (Film)item;         // 如果不能直接转换成 Film 类
                if (film.Year < 1960)
                {
                    filterFilms.Add(film);
                    Console.WriteLine($"Name={film.Name},Year={film.Year}");            // 打印筛选过的队列
                }
            }
            //foreach (Film film in filterFilms)          // 打印筛选过的队列
            //{
            //    Console.WriteLine($"Name={film.Name},Year={film.Year}");
            //}

            // public virtual void Sort(IComparer comparer)
            films.Sort(new FilmNameComparer());           //排序原始列表
            foreach (Film film in films)            // 打印排序后的集合
            {
                Console.WriteLine($"Name={film.Name},Year={film.Year}");
            }

        }

        class FilmNameComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                Film A = (Film)x;
                Film B = (Film)y;
                return A.Name.CompareTo(B.Name);
            }
        }

        class Film
        {
            private string _name;
            private int _year;

            public string Name
            {
                get
                {
                    return _name;
                }
                set
                {
                    _name = value;
                }
            }
            public int Year
            {
                get
                {
                    return _year;
                }
                set
                {
                    _year = value;
                }
            }

            public Film()
            {

            }

            public Film(string name, int year)
            {
                Name = name;
                Year = year;
            }
        }
    }
}
